using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Fated {
    internal class TimingControl {
        public double lastTick = 0.0;
        public bool tickUsed = false;
        public double TickTime = .3;
    }
    internal class Tween {
        public Vector2 start;
        public Vector2 direction;
        public double duration;
        public double elapsed = 0;
    }
    public static class TimingMngr {
        private static Dictionary<long, TimingControl> controls = new Dictionary<long, TimingControl>();
        private static Dictionary<long, Tween> tweens = new Dictionary<long, Tween>();
        private static long controlID = 0;
        private static long tweenID = 0;
        /// <summary>
        /// This method updates a control's timer and returns true
        /// if TickTime seconds has passed since it was last used.
        /// </summary>
        /// <param name="control">The control to test for use</param>
        /// <param name="controlName">The control timer to use</param>
        /// <param name="deltaT">Elapsed time in seconds</param>
        /// <returns></returns>
        public static bool tickAvailable(Vector2 control, long controlIndex, double deltaT) {
            TimingControl currControl = controls[controlIndex];

            if (currControl.lastTick > currControl.TickTime) {
                currControl.lastTick = 0;
                currControl.tickUsed = false;
            }

            // If the stick is trying to be used
            if (Math.Abs(control.Y) > 0.0001 || Math.Abs(control.X) > 0.0001) {
                // We don't want to allow a tick twice, so we set our timer zero
                if (!currControl.tickUsed) {
                    currControl.lastTick = 0;
                    currControl.tickUsed = true;
                    return true;
                }
                currControl.lastTick += deltaT;
            } else {
                // If there's no input, then the tick becomes available.
                currControl.lastTick = 0;
                currControl.tickUsed = false;
            }

            return false;
        }
        public static void setTickTime(long index, double newTickTime) {
            controls[index].TickTime = newTickTime;
        }
        public static long registerControl() {
            controls.Add(controlID, new TimingControl());
            return controlID++;
        }
        public static void unregisterControl(long index) {
            controls.Remove(index);
        }
        public static void resetTickTime(long rightStickIndex) {
            controls[rightStickIndex].TickTime = .3;
        }

        public static long createTween(Vector2 start, Vector2 dest, double duration) {
            Tween newTween = new Tween();
            newTween.start = start;
            newTween.direction = dest - start;
            newTween.duration = duration;
            
            tweens.Add(tweenID, newTween);

            return tweenID++;
        }
        public static Vector2 updateTween(long index, double elapsed) {
            Tween data = tweens[index];
            data.elapsed += elapsed;
            if (data.elapsed > data.duration) data.elapsed = data.duration;
            float percent = (float)(data.elapsed / data.duration);
            return data.start + (data.direction * percent);
        }
        public static void finishTween(long index) {
            tweens.Remove(index);
        }
        public static bool tweenFinished(long index) {
            if (tweens.ContainsKey(index) == false) return true;

            return Math.Abs(tweens[index].duration - tweens[index].elapsed) < .0001;
        }
    }
}
